#ifndef LEARNINGDATA_H
#define LEARNINGDATA_H


template<int n> class LearningData;

#include <QDebug>
#include <QList>
#include <QString>
#include <QFile>
#include <QTextStream>
#include <QMap>
#include <set>
#include <algorithm>
#include "state.h"
#include "cell.h"
#include "node.h"
#include "key.h"
#include "../Systems/abstractsystem.h"

template<int n>
class LearningData
{
    friend class Cell<n>;
    friend class Learner<n>;

private:
    //System we will learn
    AbstractSystem* sys;

    //Cell vertices
    QList<State<n> > states;

    //The tree contains the cells, and the map allow efficient access
    Node tree;
    QMap<Key<n>, AbstractNode* > lookupMap;

    //Learning rates
    double alpha, beta;

    //To access the less visited cells
    int threshold;
    QList<std::set<Cell<n>*> > sets;

    //Others
    int nbMotors ,dimPos , cellNumber , maxLevel ;
    double maxV;

public:

    //Constructors
    LearningData(){ }
    LearningData(QString filename);
    LearningData(double a_alpha, double a_beta, int threshold , int _nbMotors , int dimPos);

    //Export function
    void exportData(QString filename);

    //Uses states and maxLevel to reconstruct the tree and the map
    void reconstruct();

    //Insertion of a new cell vertex (returns its id in states)
    int insert(State<n> s);

    //Map modification (inserting new cells, replacing an old cell by a node)
    void insert(Cell<n> *cell);
    void replace(Cell<n> *cell, Node *node);

    //Updates the sets and nVisits in the cell
    void visit(Cell<n> *cell);

    //Returns pointer on one of the cells with a minimal number of visits (0 if all nVisits == threshold)
    Cell<n>* getLessVisited();
    int getToVisit();

    //Returns pointer on the cell containing a given state
    Cell<n>* getCell(QList<double> list);

    //Others
    State<n> barycenter(QList<int> list );
    QList<double> randomParams(QList<int> list);


    //Prints all cells in the tree
    void print()
    {
        tree.print();
    }
};

#include "learningdata.hpp"

#endif // LEARNINGDATA_H
